package com.cal.utms.valuation;

import java.util.Calendar;
import java.util.Date;

import com.cal.utms.entity.Deal;

public class FixedDepositeCalculator {

	private double withholdingTax;
	private double maturityValue;
	private double effectiveRate;
	private int tenor;
	private int dayCount = 365;
	//Eod Params
	private double dailyInterest;
	private double marketValueCpa;
	private int daysInInterest;

	public void valuateAllParameters(Deal deal){
		double principleValue = deal.getDealValue().doubleValue();
		double actualRate = deal.getActualRate().doubleValue();
		String dayCountInput = deal.getDayBasis();
		Date valueDate = deal.getValueDate();
		Date maturityDate = deal.getMaturityDate();
		String withholdTaxType = deal.getWithholdingTax();
		double withholdingTaxRate = 0;
		if(deal.getWithholdingTaxRate()!=null)
			withholdingTaxRate = deal.getWithholdingTaxRate().doubleValue();
		double icp = 0;
		if(deal.getIcp()!=null)
			icp = deal.getIcp().doubleValue();
		valuateAllParameters(principleValue, actualRate, dayCountInput, valueDate, maturityDate, withholdTaxType, withholdingTaxRate, icp);
	}
	
	public void valuateEodParams(Deal deal, Date valueDate){
		valuateAllParameters(deal);
		daysInInterest = ((int)((valueDate.getTime() - deal.getValueDate().getTime())/(1000 * 60 * 60 * 24)))+1;
		dailyInterest = deal.getDealValue().doubleValue()*(effectiveRate/100)/dayCount;
		marketValueCpa = deal.getDealValue().doubleValue() + deal.getDealValue().doubleValue()*(effectiveRate/100)*((double)daysInInterest/(double)dayCount);
	}

	public synchronized void valuateAllParameters(final double principleValue, double actualRate, String dayCountInput, final Date valueDate, Date maturityDate, String withholdTaxType, double withholdingTaxRate, double icp){
		tenor = (int)((maturityDate.getTime() - valueDate.getTime())/(1000 * 60 * 60 * 24));
		actualRate = actualRate/100;
		withholdingTaxRate = withholdingTaxRate/100;
		int tempTenor = tenor;
		if(dayCountInput.equals("Act / 360")){
			dayCount = 360;
		}else if(dayCountInput.equals("Act / 364")){
			dayCount = 364;
		}else if(dayCountInput.equals("30 / 360")){
			dayCount = 360;
		}
		if(icp==0){
			valuate(principleValue, actualRate, dayCount, tenor, withholdTaxType, withholdingTaxRate);
			if(!withholdTaxType.equals("Upfront")){
				maturityValue = maturityValue - withholdingTax;
			}
		}else{
			Date icpDate = null;
			Calendar cal = Calendar.getInstance();
	        cal.setTime(valueDate);
	        cal.add(Calendar.MONTH, (int)icp);
	        icpDate =  cal.getTime();
	        double invest = principleValue;
	        Date startingDate = valueDate;
	        double tempMatVal = 0;
	        double tempWithholdTax = 0;
	        while(icpDate.compareTo(maturityDate)<0){
	        	 tempTenor = (int)((icpDate.getTime() - startingDate.getTime())/(1000 * 60 * 60 * 24));
	        	 valuate(invest, actualRate, dayCount, tempTenor, withholdTaxType, withholdingTaxRate);

	        	 invest = this.maturityValue;
	        	 startingDate = icpDate;
	        	 cal.setTime(icpDate);
	        	 cal.add(Calendar.MONTH, (int)icp);
	        	 icpDate = cal.getTime();
	        	 tempWithholdTax = tempWithholdTax+this.withholdingTax;
	     
	        }
	        tempTenor = (int)((maturityDate.getTime() - startingDate.getTime())/(1000 * 60 * 60 * 24));
	        valuate(invest, actualRate, dayCount, tempTenor, withholdTaxType, withholdingTaxRate);
	        tempMatVal = this.maturityValue;
        	tempWithholdTax = tempWithholdTax+this.withholdingTax;
	        
	        if(!withholdTaxType.equals("Upfront")){
				tempWithholdTax = (tempMatVal-principleValue)*withholdingTaxRate;
				tempMatVal = tempMatVal - tempWithholdTax;
			}
	        this.maturityValue = tempMatVal;
	        this.withholdingTax = tempWithholdTax;
		}
		effectiveRate = ((this.maturityValue-principleValue)/principleValue)*((double)dayCount/(double)tenor)*100;
	}
	
	public synchronized void valuate(double principleValue, double actualRate, double dayBasis, double tenor, String withholdTaxType, double withholdingTaxRate){
		if(withholdTaxType.equals("Upfront")){
			withholdingTax = ((actualRate*tenor*withholdingTaxRate/dayBasis)/(1+(actualRate*tenor*withholdingTaxRate/dayBasis)))*principleValue;
			maturityValue = ((1+actualRate*tenor/dayBasis)/(1+(actualRate*tenor*withholdingTaxRate/dayBasis)))*principleValue;
		}else{
			withholdingTax = principleValue*actualRate*withholdingTaxRate*(tenor/dayBasis);
			maturityValue = principleValue + principleValue*actualRate*(tenor/dayBasis);
		}	
	}
	
	

	public double getWithholdingTax() {
		return withholdingTax;
	}
	public void setWithholdingTax(double withholdingTax) {
		this.withholdingTax = withholdingTax;
	}
	public double getMaturityValue() {
		return maturityValue;
	}
	public void setMaturityValue(double maturityValue) {
		this.maturityValue = maturityValue;
	}
	public double getEffectiveRate() {
		return effectiveRate;
	}
	public void setEffectiveRate(double effectiveRate) {
		this.effectiveRate = effectiveRate;
	}
	public int getTenor() {
		return tenor;
	}
	public void setTenor(int tenor) {
		this.tenor = tenor;
	}
	
	public double getMarketValueCpa() {
		return marketValueCpa;
	}

	public void setMarketValueCpa(double marketValueCpa) {
		this.marketValueCpa = marketValueCpa;
	}

	public int getDaysInInterest() {
		return daysInInterest;
	}

	public void setDaysInInterest(int daysInInterest) {
		this.daysInInterest = daysInInterest;
	}

	public int getDayCount() {
		return dayCount;
	}
	public void setDayCount(int dayCount) {
		this.dayCount = dayCount;
	}

	public double getDailyInterest() {
		return dailyInterest;
	}

	public void setDailyInterest(double dailyInterest) {
		this.dailyInterest = dailyInterest;
	}

}
